import os

import httpx
from langgraph_sdk import Auth


auth = Auth()

# 从你上面创建的 `.env` 文件加载
SUPABASE_URL = os.environ["SUPABASE_URL"]
SUPABASE_SERVICE_KEY = os.environ["SUPABASE_SERVICE_KEY"]


@auth.authenticate
async def get_current_user(authorization: str | None):
    """验证 JWT 令牌并提取用户信息。"""
    assert authorization
    scheme, token = authorization.split()
    assert scheme.lower() == "bearer"

    try:
        # 使用认证提供者验证令牌
        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"{SUPABASE_URL}/auth/v1/user",
                headers={
                    "Authorization": authorization,
                    "apiKey": SUPABASE_SERVICE_KEY,
                },
            )
            assert response.status_code == 200
            user = response.json()
            return {
                "identity": user["id"],  # 唯一用户标识符
                "email": user["email"],
                "is_authenticated": True,
            }
    except Exception as e:
        raise Auth.exceptions.HTTPException(status_code=401, detail=str(e))


@auth.on
async def add_owner(ctx, value):
    """通过资源元数据使资源对创建者私有。"""
    filters = {"owner": ctx.user.identity}
    metadata = value.setdefault("metadata", {})
    metadata.update(filters)
    return filters


@auth.on.threads.create
async def on_thread_create(
        ctx: Auth.types.AuthContext,
        value: Auth.types.on.threads.create.value,
):
    """在创建线程时添加所有者。
    此处理程序在创建新线程时运行，执行两件事：
    1. 在创建的线程上设置元数据以跟踪所有权
    2. 返回一个过滤器，确保只有创建者可以访问
    """
    # 示例 value：
    #  {'thread_id': UUID('99b045bc-b90b-41a8-b882-dabc541cf740'), 'metadata': {}, 'if_exists': 'raise'}

    # 在创建的线程上添加所有者元数据
    # 此元数据随线程存储并持久化
    metadata = value.setdefault("metadata", {})
    metadata["owner"] = ctx.user.identity
    # 返回过滤器，仅限创建者访问
    return {"owner": ctx.user.identity}


@auth.on.threads.read
async def on_thread_read(
        ctx: Auth.types.AuthContext,
        value: Auth.types.on.threads.read.value,
):
    """仅允许用户读取自己的线程。
    此处理程序在读取操作时运行。由于线程已存在，无需设置元数据，
    只需返回一个过滤器，确保用户只能看到自己的线程。
    """
    return {"owner": ctx.user.identity}


@auth.on.assistants
async def on_assistants(
        ctx: Auth.types.AuthContext,
        value: Auth.types.on.assistants.value,
):
    # 为了说明目的，我们将拒绝所有涉及助手资源的请求
    # 示例 value：
    # {
    #     'assistant_id': UUID('63ba56c3-b074-4212-96e2-cc333bbc4eb4'),
    #     'graph_id': 'agent',
    #     'config': {},
    #     'metadata': {},
    #     'name': 'Untitled'
    # }
    raise Auth.exceptions.HTTPException(
        status_code=403,
        detail="用户缺乏所需权限。",
    )


# 假设你在存储中按 (user_id, resource_type, resource_id) 组织信息
@auth.on.store()
async def authorize_store(ctx: Auth.types.AuthContext, value: dict):
    # 每个存储项的“namespace”字段是一个可以视为项目录的元组
    namespace: tuple = value["namespace"]
    assert namespace[0] == ctx.user.identity, "未授权"
